% Reset all subclasses of dotsAllSingletonObjects.
% @param varargin arguments to pass to each singleton reset() method
% @details
% Invokes the reset() method of all of the subclasses of
% dotsAllSingletonObjects which are contained in Snow Dots.  @a varargin
% may contain property-value pairs to pass to each reset() method.  The
% reset() method of dotsAllSingletonObjects "knows" to ignore properties
% which are not defined for a particular subclass.
% @details
% Attempts to reset subclasses of dotsAllObjectManagers after resetting
% other singletons, in order to avoid initialization dependencies, or race
% conditions with remote servers.
% @details
% dotsResetTheSingletons() is provided for convenience, especially during
% unit testing.  Since multiple singleton subclasses may define properties
% with the same names, it may be necessary to set singleton proerties in a
% more nuanced way.  See dotsTheMachineConfiguaration.
function dotsResetTheSingletons(varargin)

% locate the Snow Dots tree.
utilitiesPath = fileparts(which('SnowDots'));
dotsPath = fullfile(utilitiesPath, '..');

% search for dotsAllSingletonObjects subclasses
dotsFiles = findFiles(dotsPath);
singletonNames = {};
managerNames = {};
for ii = 1:length(dotsFiles)
    [filePath, fileName] = fileparts(dotsFiles{ii});
    metaClass = meta.class.fromName(fileName);
    if ~isempty(metaClass)
        
        if isprop(metaClass, 'MethodList')
            metaMethods = metaClass.MethodList;
        else
            metaMethods = [metaClass.Methods{:}];
        end
        isAbstract = any([metaMethods.Abstract]);
        if ~isAbstract
            supers = superclasses(metaClass.Name);
            
            % concrete singleton subclasses
            theSingletons = 'dotsAllSingletonObjects';
            if any(strcmp(supers, theSingletons));
                singletonNames{end+1} = metaClass.Name;
            end
            
            % concrete manager subclasses
            theManagers = 'dotsAllObjectManagers';
            if any(strcmp(supers, theManagers));
                managerNames{end+1} = metaClass.Name;
            end
        end
    end
end

% reset non-managers first, with given arguments
nonManagerNames = setdiff(singletonNames, managerNames);
for ii = 1:numel(nonManagerNames)
    resetter = str2func([nonManagerNames{ii}, '.reset']);
    feval(resetter, varargin{:});
end

% reset managers first, with given arguments
for ii = 1:numel(managerNames)
    resetter = str2func([managerNames{ii}, '.reset']);
    feval(resetter, varargin{:});
end